#include "bzbfile/iniparser.h"
#include "bzbfile/file.h"
#include "bzbstring/stringutils.h"
#include "bzbutil/platform.h"
#include <fstream>


bzbfile::INIFile bzbfile::parse_ini_file(const std::string &filename) {

	INIFile res;
	std::string content = bzbfile::read(filename);
	std::string curr_section = "";

	auto lines = bzbstring::split(content, '\n');

	if(!lines.size()) {
		throw std::runtime_error("ERROR: parse_ini_file: Malformed file");
	}

	// KEY = Hello=INI=File
	//     ^ split only here

	// Keys may not contain '='

	for (const auto &line : lines) {

		if(line.size() == 0 || line.at(0) == '#') {

			// Skip if completely empty or comment
			continue;
		}
		
		if(line.at(0) == '[' && line.at(line.size() - 1) == ']') {

			// Parse section

			curr_section = line.substr(1, line.size() - 2);

		} else {

			// Parse key

			size_t equals_pos = line.find("=");

			if(equals_pos == std::string::npos) {

				// Clean up
				res.global_properties.clear();
				res.properties.clear();
				lines.clear();
				throw std::runtime_error("ERROR: parse_ini_file: Invalid field");
			}

			std::string key = line.substr(0, equals_pos);
			bzbstring::trim(key);
			std::string value = line.substr(equals_pos + 1,
									 line.size() - equals_pos - 1);
			bzbstring::trim(value);

			if(curr_section == "") {
				res.global_properties.insert(
					std::pair<std::string, std::string>(key, value));
			} else {
				res.properties[curr_section].insert(
					std::pair<std::string, std::string>(key, value));
			}

		}

	}

	return res;
}


void bzbfile::write_ini_file(const bzbfile::INIFile &ini, const std::string &filename) {

	std::ofstream stream(filename);

	if (!stream.is_open()) {
		bzbutil::throw_sys_error(errno);
	}

	for(auto i = ini.global_properties.begin(); i != ini.global_properties.end(); ++i) {

		stream << i->first << "=" << i->second << "\n";
	}

	for(auto i = ini.properties.begin();
		i != ini.properties.end();
		++i) {

		stream << "[" << i->first << "]" << "\n";

		for(auto l = i->second.begin(); l != i->second.end(); ++l) {
			stream << l->first << "=" << l->second << "\n";
		}

	}

}
